package com.markerhub.security;

import cn.hutool.core.util.StrUtil;
import com.markerhub.entity.SysUser;
import com.markerhub.security.UserDetailServiceImpl;
import com.markerhub.service.SysUserService;
import com.markerhub.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

public class JwtAuthenticationFilter extends BasicAuthenticationFilter {

	private JwtUtils jwtUtils;
	private UserDetailServiceImpl userDetailService;
	private SysUserService sysUserService;

	// URL白名单，与SecurityConfig保持一致
	private static final List<String> URL_WHITELIST = Arrays.asList(
		"/api/auth/login",
		"/api/auth/logout",
		"/api/auth/sys/userInfo", // 用户信息接口放回白名单
		"/api/sys-menu/nav", // 导航菜单接口放回白名单
		"/favicon.ico",
		"/swagger-ui.html",
		"/swagger-ui/",
		"/swagger-resources/",
		"/swagger-resources",
		"/v2/api-docs",
		"/v3/api-docs/",
		"/webjars/",
		"/api-docs/",
		"/api-docs"
	);

	// 构造函数注入依赖
	public JwtAuthenticationFilter(AuthenticationManager authenticationManager, JwtUtils jwtUtils, 
	                              UserDetailServiceImpl userDetailService, SysUserService sysUserService) {
		super(authenticationManager);
		this.jwtUtils = jwtUtils;
		this.userDetailService = userDetailService;
		this.sysUserService = sysUserService;
	}

	@Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        System.out.println("========== JwtAuthenticationFilter开始处理请求 ==========");
        System.out.println("请求URI: " + request.getRequestURI());
        
        // 1. 跳过白名单接口的验证
        if (isUrlWhitelisted(request.getRequestURI())) {
            System.out.println("请求URI在白名单中，跳过验证: " + request.getRequestURI());
            chain.doFilter(request, response);
            return;
        }

        try {
            // 2. 从请求头获取token - 增强版token提取逻辑
            String token = extractToken(request);
            System.out.println("从请求中提取的token: " + (token == null ? "null" : (token.length() > 20 ? token.substring(0, 20) + "..." : token)));
            
            // 3. 验证token
            if (token != null && !token.isEmpty()) {
                System.out.println("开始验证token...");
                
                // 解析token
                Claims claims = jwtUtils.getClaimByToken(token);
                if (claims != null) {
                    // 检查token是否过期
                    if (jwtUtils.isTokenExpired(claims)) {
                        System.out.println("token已过期");
                        // 不设置认证信息，让后续处理继续
                    } else {
                        // token有效，从token中获取用户信息
                        String username = claims.getSubject();
                        System.out.println("从token中获取的用户名: " + username);
                        
                        // 检查当前SecurityContext中是否已有认证信息
                        Authentication existingAuth = SecurityContextHolder.getContext().getAuthentication();
                        if (existingAuth == null || !existingAuth.isAuthenticated() || !(existingAuth.getPrincipal() instanceof UserDetails) || !username.equals(existingAuth.getName())) {
                            // 获取用户的权限等信息
                            SysUser sysUser = sysUserService.getByUsername(username);
                            System.out.println("根据用户名查询到用户: " + (sysUser == null ? "不存在" : "存在"));
                            
                            if (sysUser == null) {
                                System.out.println("用户不存在");
                                // 不设置认证信息，让后续处理继续
                            } else {
                                // 加载用户详情
                                UserDetails userDetails = userDetailService.loadUserByUsername(username);
                                System.out.println("成功加载用户详情: " + userDetails.getUsername());
                                
                                // 构建用户认证信息
                                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
                                        userDetails, null, userDetails.getAuthorities());
                                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                                
                                // 设置认证信息到SecurityContext
                                SecurityContextHolder.getContext().setAuthentication(authentication);
                                System.out.println("已设置SecurityContext认证信息，权限数量: " + userDetails.getAuthorities().size());
                            }
                        } else {
                            System.out.println("SecurityContext中已有有效的认证信息，不需要重新设置");
                        }
                    }
                } else {
                    System.out.println("token解析失败，claims为null");
                }
            } else {
                System.out.println("token为空，不设置认证信息");
            }
        } catch (Exception e) {
            System.out.println("JwtAuthenticationFilter处理异常: " + e.getMessage());
            e.printStackTrace();
            // 清除认证信息，确保不会保留无效的认证状态
            SecurityContextHolder.clearContext();
        }

        chain.doFilter(request, response);
    }
    
    /**
     * 判断URL是否在白名单中
     */
    private boolean isUrlWhitelisted(String requestUri) {
        for (String whiteUrl : URL_WHITELIST) {
            // 对于以/结尾的URL，检查是否是前缀匹配
            if (whiteUrl.endsWith("/")) {
                if (requestUri.startsWith(whiteUrl)) {
                    return true;
                }
            }
            // 精确匹配
            else if (requestUri.equals(whiteUrl)) {
                return true;
            }
        }
        return false;
    }
    
        private String extractToken(HttpServletRequest request) {
        String token = null;
        
        // 1. 直接从Authorization头获取（前端使用的标准方式）
        String authHeader = request.getHeader("Authorization");
        if (StrUtil.isNotBlank(authHeader)) {
            token = authHeader; // 保留完整的token，让JwtUtils内部处理Bearer前缀
        }
        
        // 2. 如果为空，尝试从自定义JWT头获取
        if (StrUtil.isBlank(token)) {
            String jwtHeader = jwtUtils.getHeader();
            token = request.getHeader(jwtHeader);
        }
        
        // 3. 如果仍然为空，尝试从请求参数获取
        if (StrUtil.isBlank(token)) {
            token = request.getParameter("token");
        }
        
        return token;
    }
}
